package cn.sxt.logistics.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import cn.sxt.logistics.shiro.CustomRealm;
import cn.sxt.logistics.shiro.MyFormAuthenticationFilter;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.LogoutFilter;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Properties;

@Configuration
public class ShiroConfig {

    /*配置Shiro方言，让Thymeleaf支持Shiro标签*/
    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }


    /*配置Shiro框架的核心过滤器*/

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(){

        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();

        /*配置自定义的过滤器*/
        HashMap<String, Filter> filters = new HashMap<>();
        /*设置自定义配置退出过滤器为默认 logou过滤器*/
        filters.put("logout",logoutFilter());
        /*设置自定义退出认证过滤器为默认的 authc 表单认证过滤器*/
        filters.put("authc",myFormAuthenticationFilter());

        factoryBean.setFilters(filters);

        /*配置安全管理器（核心对象）*/
        factoryBean.setSecurityManager(securityManager());

        /*配置没有认证强制访问或者认证失败跳转的地址*/
        factoryBean.setLoginUrl("/admin/login");
        /*认证成功的跳转地址*/
        factoryBean.setSuccessUrl("/index");


        HashMap<String, String> filterChainDefinitionMap = new HashMap<>();
        /*配置匿名过滤器要放行的资源*/
        filterChainDefinitionMap.put("/h-ui/**","anon");
        filterChainDefinitionMap.put("/h-ui.admin/**","anon");
        filterChainDefinitionMap.put("/lib/**","anon");
        filterChainDefinitionMap.put("/admin/loginPage","anon");
        /*配置退出过滤器*/
        filterChainDefinitionMap.put("/logout","logout");

        /*配置表单认证滤器*/
        filterChainDefinitionMap.put("/**","authc");

        factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        System.out.println("factoryBean :"+factoryBean);
        return factoryBean;
    }

    /*自定义表单认证过滤器*/
    public MyFormAuthenticationFilter myFormAuthenticationFilter(){
        MyFormAuthenticationFilter myFormAuthenticationFilter = new MyFormAuthenticationFilter();
        myFormAuthenticationFilter.setUsernameParam("username");
        myFormAuthenticationFilter.setPasswordParam("password");
        myFormAuthenticationFilter.setRememberMeParam("rememberMe");

        return myFormAuthenticationFilter;
    }

    /*自定义配置退出过滤器*/
    public LogoutFilter logoutFilter(){
        LogoutFilter logoutFilter = new LogoutFilter();
        logoutFilter.setRedirectUrl("/admin/loginPage");
        return logoutFilter;
    }

    /*配置安全管理器*/
    @Bean
    public DefaultWebSecurityManager securityManager(){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        /*配置自定义Realm*/
        securityManager.setRealm(customRealm());
        /*设置缓存管理器*/
        securityManager.setCacheManager(cacheManager());
        /*配置记住我管理器*/
        securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }

    /*配置记住我管理器（Cookie管理器）*/
    @Bean
    public RememberMeManager rememberMeManager(){
        /*创建Cookie记住我管理器*/
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        /*创建Cookie对象设置信息*/
        Cookie cookie = new SimpleCookie(CookieRememberMeManager.DEFAULT_REMEMBER_ME_COOKIE_NAME);
        cookie.setHttpOnly(true);
        /*有效期三天*/
        cookie.setMaxAge(3600 * 24 * 3);

        cookieRememberMeManager.setCookie(cookie);

        return cookieRememberMeManager;
    }

    /*配置Realm使用的缓存管理器*/
    @Bean
    public CacheManager cacheManager(){
        EhCacheManager ehCacheManager = new EhCacheManager();
        return ehCacheManager;
    }



    /*配置自定义Realm*/
    @Bean
    public CustomRealm customRealm(){
        CustomRealm customRealm = new CustomRealm();
        /*配置凭证匹配器*/
        customRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return  customRealm;
    }
    /*配置凭证匹配器*/
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("MD5");
        credentialsMatcher.setHashIterations(3);
        return credentialsMatcher;
    }
    /*开启Shiro的注解支持配置*/
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){

        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager());

        return  advisor;
    }

    /*设置Spring框架支持集成其他框架可以使用AOP*/
    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        /*设置可以让Shiro框架使用AOP为表现层创建代理（Shiro权限判断的注解全部在表现层）*/
        autoProxyCreator.setProxyTargetClass(true);
        return autoProxyCreator;
    }

    //创建对SpringMVC抛出异常处理解析器
    @Bean
    public SimpleMappingExceptionResolver simpleMappingExceptionResolver(){
        Properties properties = new Properties();
        /**
         * key :org.apache.shiro.authz.UnauthorizedException 异常
         * value ：unauthorized 只需要要讲对应的页面存放到前后缀对应的目录下面，SpringMVC自动解析
         * */
        properties.put("org.apache.shiro.authz.UnauthorizedException","unauthorized");
        SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver();
        simpleMappingExceptionResolver.setExceptionMappings(properties);

        return simpleMappingExceptionResolver;
    }








}
